%skeleton "lalr1.cc"

%defines
%define api.token.constructor
%define api.value.type variant
%define parse.assert

%code requires {
  class Driver;
}

%param { Driver& drv } // 传递一个Driver对象给bison，随后就可以使用对象中的数据成员和方法

%locations

%define parse.trace
%define parse.error verbose

// 以上代码都别动

%code {
#include "driver.h"
using namespace std;
extern ostringstream buffer;
void pop2() {
    buffer << "pop ebx\n";
    buffer << "pop eax\n";
}

void neg() {
    buffer << "pop eax\n";
    buffer << "neg eax\n";
    buffer << "push eax\n";
}

void not1() {
     buffer << " pop eax" << endl;
      buffer << " cmp eax, 0" << endl;
      buffer << " sete al" << endl;
      buffer << " movzx eax, al" << endl;
      buffer << " push eax" << endl;
}

void bitnot() {
    buffer << "pop eax\n";
    buffer << "not eax\n";
    buffer << "push eax\n";
}

void mul() {
    pop2();
    buffer << "imul eax, ebx\n";
    buffer << "push eax\n";
}

void div() {
    pop2();
    buffer << "cdq\n";
    buffer << "idiv ebx\n";
    buffer << "push eax\n";
}

void mod() {
    pop2();
    buffer << "cdq\n";
    buffer << "idiv ebx\n";
    buffer << "push edx\n";
}

void add() {
    pop2();
    buffer << "add eax, ebx\n";
    buffer << "push eax\n";
}

void sub() {
    pop2();
    buffer << "sub eax, ebx\n";
    buffer << "push eax\n";
}

void compare(int cmp) {
    pop2();
    buffer << "cmp eax, ebx\n";
    switch (cmp) {
        case 1:
            buffer << "setl al\n";
            break;
        case 2:
            buffer << "setle al\n";
            break;
        case 3:
            buffer << "setg al\n";
            break;
        case 4:
            buffer << "setge al\n";
            break;
        case 5:
            buffer << "sete al\n";
            break;
        case 6:
            buffer << "setne al\n";
            break;
    }
    buffer << "movzx eax, al\n";
    buffer << "push eax\n";
}

void less_than() {
    pop2();
    buffer << "cmp eax, ebx\n";
    buffer << "setl al\n";
    buffer << "movzx eax, al\n";
    buffer << "push eax\n";
}

void greater_than() {
    pop2();
    buffer << "cmp eax, ebx\n";
    buffer << "setg al\n";
    buffer << "movzx eax, al\n";
    buffer << "push eax\n";
}

void lessequ() {
    compare(2);
}



void greaterequ() {
    compare(4);
}

void equ() {
    compare(5);
}

void notequ() {
    compare(6);
}

void bitand1() {
    pop2();
    buffer << "and eax, ebx\n";
    buffer << "push eax\n";
}

void bitor1() {
    pop2();
    buffer << "or eax, ebx\n";
    buffer << "push eax\n";
}

void bitxor() {
    pop2();
    buffer << "xor eax, ebx\n";
    buffer << "push eax\n";
}

void and1() {
    pop2();
      buffer << " and eax, ebx" << endl;
      buffer << " setne al" << endl;
      buffer << " movzx eax, al" << endl;
      buffer << " push eax" << endl;
}

void or1() {
    pop2();
      buffer << " or eax, ebx" << endl;
      buffer << " setne al" << endl;
      buffer << " movzx eax, al" << endl;
      buffer << " push eax" << endl;
}


void printBuffer() {
    cout << buffer.str();
}

}

%define api.token.prefix {T_}
%token 
  END 0 "end of file"
  LPAREN  "("
  RPAREN  ")"
  COMMA ","
  SEMICOLON ";"
  LAND "&&"
  LOR "||"
  LNOT "!"
  PLUS "+"
  MINUS "-"
  TIMES "*"
  DIVIDE "/"
  MOD "%"
  LT "<"
  LE "<="
  GT ">"
  GE ">="
  EQ "=="
  NE "!="
  BAND "&"
  BOR "|"
  BXOR "^"
  ASSIGN "="
  LBRACE "{"
  RBRACE "}"
  BITNOT "~"

%token VOID "void" INT "int" RETURN "return" MAIN "main"  WHILE "while" IF "if" ELSE "else" CONTINUE "continue" BREAK "break" 

%token <std::string> IDENTIFIER "identifier"
%token <int> INTEGER "number"
// 在这里指定运算符的优先级和结合性，left为左结合，right为右结合，越靠下优先级越高
%precedence THEN//解决嵌套循环
%precedence ELSE
%left "||"
%left "&&"
%left "|"
%left "^"
%left "&"
%left "==" "!="
%left "<" ">" "<=" ">="
%left "+" "-"
%left "*" "/" "%"
%left UMINUS
%right "!" "~"



%nterm <int>  list_param list_parameter list_parameters

%nterm <int> parameters // 函数调用参数个数
%nterm <int> parameter body_function bodys_function
%nterm call_f// 非终结符类型也需要指定，这个与下面的例子适配，可以删除或根据需要添加，如果不需要属性文法也可以不指定类型
%type  assignment_s return_s declaration_s variables variable 
%type   value_type
%type  function  main_function normal_function 

%%
// 在这里写文法规则和动作
%start program; // 文法开始符号

program: 
%empty {}
|program function 

function://其中一个函数
main_function
//main函数
|normal_function//普通函数

//普通函数
normal_function:
value_type "identifier" {
    drv.functionArgsTable.clear();
    drv.functionArgsCount = 0;
}"(" list_parameters{
    drv.identifierTable.clear();
    drv.identifierCount = 0;
} ")" "{" bodys_function {
    cout << $2 << ":" << endl;
      cout << " push ebp" << endl;
      cout << " mov ebp, esp" << endl;
      if(drv.identifierCount > 0)
        cout << " sub esp, " << drv.identifierCount * 4 << endl;
      printBuffer();
      buffer.str("");
      if(!$9){//没有return语句
        if(drv.identifierCount > 0)
          cout << " add esp, " << drv.identifierCount * 4 << endl;
        cout << " leave" << endl;
        cout << " ret" << endl;
      }
}"}"

value_type:
  VOID             
| INT              

list_parameters:
%empty {$$=0;}
|list_param{$$=$1;}

list_param:
list_parameter{$$=1;}
|list_param "," list_parameter{$$=$1+1;}

list_parameter:
"int" "identifier"{
    drv.functionArgsTable[$2] = ++drv.functionArgsCount;
    
}


main_function:
value_type "main"{
    drv.functionArgsTable.clear();
    drv.functionArgsCount = 0;
}"(" list_parameters{
    drv.identifierTable.clear();
    drv.identifierCount = 0;
} ")" "{"bodys_function {
    cout << "main" << ":" << endl;
      cout << " push ebp" << endl;
      cout << " mov ebp, esp" << endl;
      if(drv.identifierCount > 0)
        cout << " sub esp, " << drv.identifierCount * 4 << endl;
      printBuffer();
      buffer.str("");
      
} "}"

bodys_function:
%empty {$$=0;}
|bodys_function body_function  {$$=$2;}
 // 不确定有多少行

body_function:
declaration_s{$$=0;}
|assignment_s{$$=0;}
|return_s{$$=1;}
|call_f ";"{$$=0;}
|if_else{$$=0;}
|while_s{$$=0;}
| "continue" ";"
    {
      buffer << " jmp " << drv.continue_vector.back() << endl;
    }
| "break" ";"
    {
      buffer << " jmp " << drv.break_vector.back() << endl;
    };

if_else:
IF "(" exp ")"
    {
      drv.ifCount++;
      buffer << " pop eax" << endl;
      buffer << " cmp eax, 0" << endl;
      buffer << " je " << ".L_if_end_" << drv.ifCount << endl;
      drv.if_vector.push_back(".L_else_end_" + to_string(drv.ifCount));
      drv.if_vector.push_back(".L_if_end_" + to_string(drv.ifCount));
    }
    "{"bodys_function"}" else_s
    
else_s:
  %empty %prec THEN
    {
      buffer << drv.if_vector.back() << ":" << endl;
      drv.if_vector.pop_back();
      drv.if_vector.pop_back();
    }
| ELSE
    {
      string tmp = drv.if_vector.back();
      drv.if_vector.pop_back();
      buffer << " jmp " << drv.if_vector.back() << endl;
      buffer << tmp << ":" << endl;
    } 
  "{"bodys_function"}"
    {
      buffer<< drv.if_vector.back() << ":" << endl;
      drv.if_vector.pop_back();
    
    }

while_s:
  WHILE "(" 
    {
      drv.whileCount++;
      buffer<< ".L_while_cond_" << drv.whileCount << ":" << endl;
      drv.continue_vector.push_back(".L_while_cond_" + to_string(drv.whileCount));
      drv.break_vector.push_back(".L_while_end_" + to_string(drv.whileCount));
    }
  exp
    {
      buffer << " pop eax" << endl;
      buffer << " cmp eax, 0" << endl;
      buffer << " je " << drv.break_vector.back() << endl;
    }
  ")" "{"bodys_function
    {
      buffer << " jmp " << drv.continue_vector.back() << endl;
      buffer << drv.break_vector.back() << ":" << endl;
      drv.continue_vector.pop_back();
      drv.break_vector.pop_back();
    
    }"}"
//定义语句
declaration_s: "int" variables  ";"

variables:
%empty{}
|variables variable


variable: 
"identifier" {
    drv.identifierTable[$1] = ++drv.identifierCount;
    buffer << " mov DWORD PTR [ebp-" << drv.identifierTable[$1] * 4 << "], 0" << endl;
    
}
|","
|"identifier" "=" exp{
    drv.identifierTable[$1] = ++drv.identifierCount;
    buffer << " pop eax" << endl;
    buffer << " mov DWORD PTR [ebp-" << drv.identifierTable[$1] * 4 << "], eax" << endl;
}

//赋值语句
assignment_s:
"identifier" "=" exp ";"{
      buffer << " pop eax" << endl;
      if(drv.functionArgsTable.count($1)){
        buffer << " mov DWORD PTR [ebp+" << 8 + 4 * (drv.functionArgsCount - drv.functionArgsTable[$1]) << "], eax" << endl;
      }
      else if(drv.identifierTable.count($1)){
        buffer << " mov DWORD PTR [ebp-" << drv.identifierTable[$1] * 4 << "], eax" << endl;
      }
};


//return语句
return_s:
RETURN ";"{
      if(drv.identifierCount > 0){
        buffer << " add esp, " << drv.identifierCount * 4 << endl;
      }
      buffer << " leave" << endl;
      buffer << " ret" << endl;
}
|"return" exp ";"{
    buffer << " pop eax" << endl;// 返回值
      if(drv.identifierCount > 0)
        buffer << " add esp, " << drv.identifierCount * 4 << endl;
      buffer << " leave" << endl;
      buffer << " ret" << endl;
}


exp:
    IDENTIFIER{
        if(drv.functionArgsTable.count($1)){// 函数参数
        buffer << " mov eax, " << "DWORD PTR [ebp+" << 8 + 4 * (drv.functionArgsCount - drv.functionArgsTable[$1]) << "]" << endl;
        buffer << " push eax" << endl;
      }
      else if(drv.identifierTable.count($1)){// 局部变量
        buffer << " mov eax, " << "DWORD PTR [ebp-" << drv.identifierTable[$1] * 4 << "]" << endl;
        buffer << " push eax" << endl;
      }
    }
    |call_f{
      buffer << " push eax" << endl; // 只有当函数调用作为表达式时才处理函数返回值
    }
    | INTEGER
    {
      buffer << " push " << $1 << endl;
    }
    | exp PLUS exp {  add(); }
    | exp MINUS exp { sub(); }
    | exp TIMES exp { mul(); }
    | exp DIVIDE exp { div(); }
    | exp MOD exp {  mod(); }
    | exp LT exp {  less_than(); }
    | exp LE exp {  lessequ(); }
    | exp GT exp {  greater_than(); }
    | exp GE exp {  greaterequ(); }
    | exp "=="exp {  equ(); }
    | exp "!=" exp { notequ(); }
    | exp "&&" exp { and1(); }
    | exp "&" exp { bitand1(); }
    | exp "|" exp { bitor1(); }
    | exp "^" exp { bitxor(); }
    | exp "||" exp {  or1(); }
    | "~" exp {   bitnot();    }
    | "!" exp {  not1(); }
    | "-" exp %prec UMINUS { neg(); }
    | LPAREN exp RPAREN 
;
call_f:

    IDENTIFIER "(" parameters ")"
    {
      if($1 == "println_int"){
        buffer << " push offset format_str" << endl;
        buffer << " call printf" << endl;
        buffer << " add esp, 8" << endl;
      }
      else{
        buffer << " call " << $1 << endl;
        buffer << " add esp, " << $3 * 4 << endl; // 释放参数空间
      }
    };

parameters:
%empty 
    {
      $$ = 0;
    }
| parameter
    {
      $$ = $1;
    };

parameter:
  exp
    {
      $$ = 1;
    }
| parameter "," exp
    {
      $$ = $1 + 1;
    };


%%

void yy::parser::error (const location_type& l, const std::string& m)
{// 不用管这个函数，用于当解析文件出错输出，可以用来调试文法规则
  std::cerr << l << ": " << m << '\n';
}